/** @jsxImportSource @emotion/react */
import { jsx } from "@emotion/react";
import * as React from "react";
import { IconButtonProps } from "./IconButton";
import { animated } from "@react-spring/web";
// import { useTheme } from "./Theme/Providers";
// import { mergeRefs } from "./Hooks/merge-refs";
import {
    useFloating,
    autoUpdate,
    offset,
    flip,
    shift,
    useClick,
    useDismiss,
    useRole,
    useInteractions,
    Placement,
    FloatingPortal,
    FloatingFocusManager,
    useId
} from "@floating-ui/react";
import { mergeRefs } from "react-merge-refs";
import {
    useTheme,
} from "customize-easy-ui-component";


interface FloatPopover1Props {
    isOpen?: boolean;
    // children: React.ReactElement<ButtonProps | IconButtonProps>;
    content: React.ReactNode;
    closeOnMenuItemClick?: boolean;
    // placement?: Placements;
}

interface PopoverOptions {
    initialOpen?: boolean;
    //declare type AlignedPlacement = `${Side}-${Alignment}`;
    placement?: Placement;
    modal?: boolean;
    open?: boolean;
    onOpenChange?: (open: boolean) => void;
}

export function usePopover({
                               initialOpen = false,
                               placement,
                               modal = true,
                               open: controlledOpen,
                               onOpenChange: setControlledOpen
                           }: PopoverOptions = {}) {
    const [uncontrolledOpen, setUncontrolledOpen] = React.useState(initialOpen);
    const [labelId, setLabelId] = React.useState<string | undefined>();
    const [descriptionId, setDescriptionId] = React.useState<
        string | undefined
        >();

    const open = controlledOpen ?? uncontrolledOpen;
    const setOpen = setControlledOpen ?? setUncontrolledOpen;

    const data = useFloating({
        placement,
        open,
        onOpenChange: setOpen,
        whileElementsMounted: autoUpdate,
        middleware: [offset(5), flip(), shift()]
    });

    const context = data.context;

    const click = useClick(context, {
        enabled: controlledOpen == null
    });
    const dismiss = useDismiss(context);
    const role = useRole(context);

    const interactions = useInteractions([click, dismiss, role]);

    return React.useMemo(
        () => ({
            open,
            setOpen,
            ...interactions,
            ...data,
            modal,
            labelId,
            descriptionId,
            setLabelId,
            setDescriptionId
        }),
        [open, setOpen, interactions, data, modal, labelId, descriptionId]
    );
}

type ContextType =
    | (ReturnType<typeof usePopover> & {
    setLabelId: React.Dispatch<React.SetStateAction<string | undefined>>;
    setDescriptionId: React.Dispatch<
        React.SetStateAction<string | undefined>
        >;
})
    | null;

const PopoverContext = React.createContext<ContextType>(null);

export const usePopoverState = () => {
    const context = React.useContext(PopoverContext);

    if (context == null) {
        throw new Error("Popover components must be wrapped in <Popover />");
    }

    return context;
};

/*例子  https://codesandbox.io/s/distracted-swirles-jo1pvu?file=/src/App.tsx
* */
export function FloatPopover({
                            children,
                            modal = false,
                            ...restOptions
                        }: {
    children: React.ReactNode;
} & PopoverOptions) {
    // This can accept any props as options, e.g. `placement`,
    // or other positioning options.
    const popover = usePopover({ modal, ...restOptions });
    return (
        <PopoverContext.Provider value={popover}>
            {children}
        </PopoverContext.Provider>
    );
}

interface PopoverReferProps {
    children: React.ReactNode;
    asChild?: boolean;
}

//popover对话框跟随参考位置的DIV；  以及可选的 绑定onClick开启显示。
export const PopoverRefer = React.forwardRef<
    HTMLElement,
    React.HTMLProps<HTMLElement> & PopoverReferProps
    >(function PopoverRefer({ children, asChild = false, ...props }, propRef) {
    const state = usePopoverState();
    const childrenRef = (children as any).ref;

    const ref = React.useMemo(
        () => mergeRefs([state.reference, propRef, childrenRef]),
        [state.reference, propRef, childrenRef]
    );


    //自定义版： `asChild` allows the user to pass any element as the anchor
    if (asChild && React.isValidElement(children)) {
        return React.cloneElement(
            children,
            state.getReferenceProps({
                ref,
                ...props,
                ...children.props,
                "data-state": state.open ? "open" : "closed"
            })
        );
    }

    //正常的按钮版；
    return (
        <button
            ref={ref}
            // The user can style the trigger based on the state
            data-state={state.open ? "open" : "closed"}
            {...state.getReferenceProps(props)}
        >
            {children}
        </button>
    );
});

//主体部分:
export const PopoverContent = React.forwardRef<
    HTMLDivElement,
    React.HTMLProps<HTMLDivElement>
    >(function PopoverContent(props, propRef) {
    const state = usePopoverState();

    const ref = React.useMemo(() => mergeRefs([state.floating, propRef]), [
        state.floating,
        propRef
    ]);

    const theme = useTheme();

    return (
        <FloatingPortal>
            {state.open && (
                <FloatingFocusManager context={state.context} modal={state.modal}>
                    <div  className="PopoverContent"
                        ref={ref}
                        style={{
                            zIndex: theme.zIndices.popover,
                            position: state.strategy,
                            top: state.y ?? 0,
                            left: state.x ?? 0,
                            //width: "max-content",没法自适应宽度没法Wrap;
                            backgroundColor: 'white',
                            boxShadow: '0 2px 4px rgba(0, 10, 20, 0.1)',
                            border: '1px solid #ddd',
                            padding: '4px 8px',
                            borderRadius: '4px',
                            ...props.style
                        }}
                        aria-labelledby={state.labelId}
                        aria-describedby={state.descriptionId}
                        {...state.getFloatingProps(props)}
                    >
                        {props.children}
                    </div>
                </FloatingFocusManager>
            )}
        </FloatingPortal>
    );
});

export const PopoverHeading = React.forwardRef<
    HTMLHeadingElement,
    React.HTMLProps<HTMLHeadingElement>
    >(function PopoverHeading({ children, ...props }, ref) {
    const { setLabelId } = usePopoverState();
    const id = useId();

    // Only sets `aria-labelledby` on the Popover root element
    // if this component is mounted inside it.
    React.useLayoutEffect(() => {
        setLabelId(id);
        return () => setLabelId(undefined);
    }, [id, setLabelId]);

    return (
        <h2 {...props} ref={ref} id={id}>
            {children}
        </h2>
    );
});

//增加一层就为了添加一个w3c设置： aria-describedby={state.descriptionId} 屏幕阅读器 ：听觉UI@ 用途的。
export const PopoverDescription = React.forwardRef<
    HTMLParagraphElement,
    React.HTMLProps<HTMLParagraphElement>
    >(function PopoverDescription({ children, ...props }, ref) {
    const { setDescriptionId } = usePopoverState();
    const id = useId();

    // Only sets `aria-describedby` on the Popover root element
    // if this component is mounted inside it.
    React.useLayoutEffect(() => {
        setDescriptionId(id);
        return () => setDescriptionId(undefined);
    }, [id, setDescriptionId]);

    const theme = useTheme();

    return (
        <div  className="PopoverDescription"
            {...props} ref={ref} id={id}
              style={{
                  display: "flex",
                  flexWrap: 'wrap',
                  //zIndex: theme.zIndices.popover,
              }}
        >
            {children}
        </div>
    );
});

export const PopoverClose = React.forwardRef<
    HTMLButtonElement,
    React.ButtonHTMLAttributes<HTMLButtonElement>
    >(function PopoverClose({ children, ...props }, ref) {
    const state = usePopoverState();
    return (
        <button
            style={{
                display: "block",
                margin: 'auto',
            }}
            {...props} ref={ref} onClick={() => state.setOpen(false)}>
            {children}
        </button>
    );
});


/*文档例子  https://floating-ui.com/docs/react-examples
跟随弹出列表多列的菜单； https://codesandbox.io/s/nameless-glade-kz3pfc?file=/src/App.tsx
列表Select< >   https://codesandbox.io/s/shy-snowflake-kp6479?file=/src/Select.tsx
注入控制模式
  const [open, setOpen] = useState(false);
  return (
      <Popover open={open} onOpenChange={setOpen}>
        <PopoverRefer onClick={() => setOpen((v) => !v)}>
          启动</PopoverRefer>
        <PopoverContent className="Popover">
          <PopoverHeading>My popover heading</PopoverHeading>
          <PopoverDescription>My popover description</PopoverDescription>
          <PopoverClose>Close</PopoverClose>
        </PopoverContent>
      </Popover>
  );
不受到控制方式
    <FloatPopover>
        <PopoverRefer>启动</PopoverRefer>
        <PopoverContent className="Popover">
            <PopoverHeading>My popover heading</PopoverHeading>
            <PopoverDescription>        </PopoverDescription>
            <PopoverClose>Close</PopoverClose>
        </PopoverContent>
    </FloatPopover>
* */
